/*
* AudioBuilder.cpp
*
*  Created on: Mar 21, 2013
*      Author: Centny
*/

#include "AudioBuilder.h"
#include <math.h>
#include <string>
#include <assert.h>
namespace centny {
	namespace abl {
		//
		void free(AudioBlock** ab){
			if(ab&&*ab){
				delete (*ab)->data;
				delete *ab;
				*ab=0;
			}
		}
		AudioBlock* create(int rate,int bytesPerSample,void* data,int dlen,bool derivative){
			AudioBlock *ab=new AudioBlock();
			float A=(float)pow(2.0, 8*bytesPerSample-1);
			ab->data=new float[dlen];
			ab->rate=rate;
			ab->len=dlen;
			long val;
			if(derivative){
				ab->data[0]=0;
				float da,db;
				switch (bytesPerSample)
				{
				case 1:
					char t;
					t=((char*)data)[0]-128;
					val=(long)t;
					da=val*100/2/A;
					for(int i=1;i<dlen;i++){
						t=((char*)data)[i]-128;
						val=(long)t;
						db=val*100/2/A;
						ab->data[i]=db-da;
						da=db;
					}
					break;
				case 2:
					val=((long)((int*)data)[0]);
					da=val*100/2/A;
					for(int i=1;i<dlen;i++){
						val=((long)((int*)data)[i]);
						db=val*100/2/A;
						ab->data[i]=da;
						da=db;
					}
					break;
				default:
					val=((long)((long*)data)[0]);
					da=val*100/2/A;
					for(int i=1;i<dlen;i++){
						val=((long)((long*)data)[i]);
						db=val*100/2/A;
						ab->data[i]=db-da;
						da=db;
					}
					break;
				}
			}else{
				switch (bytesPerSample)
				{
				case 1:
					char t;
					for(int i=0;i<dlen;i++){
						t=((char*)data)[i]-128;
						val=(long)t;
						ab->data[i]=val*100/2/A;
					}
					break;
				default:
					for(int i=0;i<dlen;i++){
						val=((int*)data)[i];
						ab->data[i]=val*100/2/A;
					}
					break;
				}
			}
			return ab;
		}
		AudioBlock* convert(AudioBlock* src,int nrate){
			AudioBlock *ab=new AudioBlock();
			float r=(float)nrate/(float)src->rate;
			ab->len=src->len*r;
			ab->rate=nrate;
			ab->data=new float[ab->len];
			ab->data[0]=src->data[0];
			for(int i=1;i<src->len;i++){
				int nidx=(i-1)*r;
				nidx++;
				for(;nidx<=i*r;nidx++){
					ab->data[nidx]=src->data[i-1]+(src->data[i]-src->data[i-1])*((float)nidx/r-i+1);
				}
			}
			return ab;
		}
		AudioBlock* copy(AudioBlock* src){
			AudioBlock* ab=new AudioBlock();
			ab->rate=src->rate;
			ab->len=src->len;
			ab->data=new float[ab->len];
			memcpy(ab->data,src->data,src->len);
			return ab;
		}
		//
		AudioBuilder::AudioBuilder(AudioBlock* taudio,MatchHandler* mhandler) {
			this->startIdx=1;
			this->taudio=taudio;
			this->mh=mhandler;
			this->baudio=0;
		}
		void AudioBuilder::setTargetRate(int rate){
			if(this->baudio){
				free(&this->baudio);
			}
			if(rate==this->taudio->rate){
				this->baudio=copy(this->taudio);
			}else{
				this->baudio=convert(this->taudio,rate);
			}
			this->startIdx=1;
		}
		void AudioBuilder::process(AudioBlock* ab){
			assert(this->baudio&&ab&&this->baudio->rate==ab->rate);

		}
		AudioBuilder::~AudioBuilder() {
			// TODO Auto-generated destructor stub
		}
	}
} /* namespace centny */
